using System.Collections.Generic;
using UnityEngine;
using ILRuntime.Runtime.Enviorment;
using System.IO;
using ILRuntime.CLR.TypeSystem;
using System;
using System.Collections;
using System.Reflection;
using ILRuntime.CLR.Method;
using ILRuntime.Runtime.Intepreter;
using ILRuntime.Runtime.Stack;
using UnityEngine.Playables;

namespace Gj.ILRuntimeExt
{
//    public class HotfixMethod
//    {
//        public MethodBase method;
//        public string ns;
//        public string target;
//        
//        public unsafe StackObject* redirection(ILIntepreter __intp, StackObject* __esp, IList<object> __mStack, CLRMethod __method, bool isNewObj)
//        {
//            Debug.Log("HotfixMethod"+method.Name);
//            ILRuntime.Runtime.Enviorment.AppDomain __domain = __intp.AppDomain;
//            var result = __domain.Invoke(ns, target, null, null);
//            return ILIntepreter.PushObject(__esp, __mStack, result);
//        }
//    }
    public static class Projects
    {
        // 简化逻辑，全局一个实例即可
        public static ILRuntime.Runtime.Enviorment.AppDomain Domain;

        public delegate void OnInitializeDelegate();

        public static OnInitializeDelegate OnInitialize;

        private static bool isInited = false;

        public const string Extend = "";
        

        static Projects()
        {
            Domain = new ILRuntime.Runtime.Enviorment.AppDomain();
        }

        // 加载前，确保对应的bundle已经加载：Resource.LoadBundle
        public static IEnumerator Load(string project, Action<bool> callback)
        {
            if (!isInited)
            {
                isInited = true;
                // OnInitialize可以添加CLR重定向，继承适配器等
                if (OnInitialize != null) OnInitialize();
                Type a = Type.GetType("ILRuntime.Runtime.Generated.CLRBindings");
                if (a.IsClass)
                {
                    var b = a.GetMethod("Initialize");
                    b.Invoke(null, new object[]{ Domain });
                }
            }

            // 一个namespace加载一个同名project
            var ns = Resource.MainNamespace;
            if (Resource.NamespaceStatus)
            {
                ns = project;
            }

            byte[] dllBytes=null;
            yield return Resource.Download("Project/"+project + Extend, bytes =>
            {
                Debug.Log(bytes);
                Debug.Log(bytes.Length);
                dllBytes = bytes;
            }, ns);
#if UNITY_EDITOR
//                var pdb = Resource.LoadAsset<TextAsset>(project+".pdb") as TextAsset;
//            byte[] pdbBytes=null;
//            yield return Resource.Download("Project/"+project + ".pdb"+Extend, bytes =>
//            {
//                pdbBytes = bytes;
//            }, ns);
#endif
//            var dll = Resource.LoadAsset<TextAsset>(project+".dll") as TextAsset;
            try
            {
                using (var fs = new MemoryStream(dllBytes))
                {
#if UNITY_EDITOR
                    // 正式环境不加载pdb文件，也不会将pdb文件打包

//                using (var p = new MemoryStream(pdbBytes))
//                {
//                    Domain.LoadAssembly(fs, p, new PdbReaderProvider());
//                }

                    Domain.LoadAssembly(fs);
#else
                Domain.LoadAssembly(fs);
#endif
                }

                callback(true);
            }
            catch (Exception e)
            {
                Debug.LogError(e);
                callback(false);
            }
        }


        public static Type GetType(string target)
        {
            IType type = Domain.LoadedTypes[target];
            return type.ReflectionType;
        }
    }

}
